<template>
  <div class="template-refs-demo">
    <h2>模板引用和组合式API高级用法</h2>
    
    <!-- 介绍部分 -->
    <div class="introduction">
      <p>模板引用允许直接访问DOM元素和组件实例，而组合式API提供了更灵活的逻辑组织方式。</p>
    </div>

    <!-- 1. 基本模板引用 -->
    <section class="demo-section">
      <h3>1. 基本模板引用</h3>
      <div class="demo-content">
        <input
          ref="inputRef"
          type="text"
          placeholder="输入一些内容..."
          class="input"
        />
        <button @click="focusInput" class="btn">聚焦输入框</button>
        <button @click="getInputValue" class="btn">获取输入值</button>
        <button @click="setInputValue" class="btn">设置输入值</button>
      </div>
      <div v-if="inputValue" class="result">
        输入框的值: {{ inputValue }}
      </div>
    </section>

    <!-- 2. 组件引用 -->
    <section class="demo-section">
      <h3>2. 组件引用</h3>
      <div class="demo-content">
        <CounterComponent ref="counterRef" />
        <div class="controls">
          <button @click="incrementCounter" class="btn">组件方法: 增加计数</button>
          <button @click="getCounterValue" class="btn">获取计数</button>
          <button @click="resetCounter" class="btn">重置计数</button>
        </div>
        <div v-if="counterValue !== null" class="result">
          计数器当前值: {{ counterValue }}
        </div>
      </div>
    </section>

    <!-- 3. v-for 中的模板引用 -->
    <section class="demo-section">
      <h3>3. v-for 中的模板引用</h3>
      <div class="demo-content">
        <div
          v-for="(item, index) in items"
          :key="index"
          :ref="el => { if (el) itemRefs[index] = el }"
          class="item"
        >
          项目 {{ index + 1 }}: {{ item }}
        </div>
        <div class="controls">
          <button @click="highlightRandomItem" class="btn">高亮随机项目</button>
          <button @click="resetHighlights" class="btn">重置高亮</button>
        </div>
      </div>
    </section>

    <!-- 4. 响应式引用和生命周期 -->
    <section class="demo-section">
      <h3>4. 响应式引用和生命周期集成</h3>
      <div class="demo-content">
        <div ref="containerRef" class="container">
          <div class="box" v-for="i in count" :key="i">{{ i }}</div>
        </div>
        <div class="controls">
          <button @click="increaseCount" class="btn">增加方块</button>
          <button @click="decreaseCount" class="btn">减少方块</button>
          <button @click="measureContainer" class="btn">测量容器尺寸</button>
        </div>
        <div v-if="containerDimensions" class="result">
          容器尺寸: {{ containerDimensions.width }}px × {{ containerDimensions.height }}px
        </div>
      </div>
    </section>

    <!-- 5. 组合式API高级用法 -->
    <section class="demo-section">
      <h3>5. 组合式API高级用法</h3>
      <div class="demo-content">
        <div class="weather-widget">
          <h4>天气信息</h4>
          <div v-if="loading" class="loading">加载中...</div>
          <div v-else-if="error" class="error">{{ error }}</div>
          <div v-else-if="weatherData" class="weather-data">
            <div class="weather-main">
              <div class="temperature">{{ weatherData.temperature }}°C</div>
              <div class="condition">{{ weatherData.condition }}</div>
            </div>
            <div class="weather-details">
              <div class="detail">湿度: {{ weatherData.humidity }}%</div>
              <div class="detail">风速: {{ weatherData.windSpeed }} km/h</div>
              <div class="detail">气压: {{ weatherData.pressure }} hPa</div>
            </div>
          </div>
          <button @click="refreshWeather" class="btn">刷新天气</button>
        </div>
      </div>
    </section>

    <!-- 6. 自定义组合式函数 -->
    <section class="demo-section">
      <h3>6. 自定义组合式函数</h3>
      <div class="demo-content">
        <div class="mouse-tracker">
          <h4>鼠标跟踪器</h4>
          <div class="mouse-info">
            <div>X: {{ mousePosition.x }}</div>
            <div>Y: {{ mousePosition.y }}</div>
          </div>
          <div class="tracker-dot" :style="{ left: mousePosition.x + 'px', top: mousePosition.y + 'px' }"></div>
        </div>
        
        <div class="stopwatch">
          <h4>秒表</h4>
          <div class="time">{{ formattedTime }}</div>
          <div class="controls">
            <button @click="startStop" class="btn">
              {{ isRunning ? '停止' : '开始' }}
            </button>
            <button @click="reset" class="btn">重置</button>
          </div>
        </div>
      </div>
    </section>
  </div>
</template>

<script setup>
import { ref, reactive, onMounted, onUnmounted, nextTick, watch } from 'vue'

// 1. 基本模板引用
const inputRef = ref(null)
const inputValue = ref('')

const focusInput = () => {
  if (inputRef.value) {
    inputRef.value.focus()
  }
}

const getInputValue = () => {
  if (inputRef.value) {
    inputValue.value = inputRef.value.value
  }
}

const setInputValue = () => {
  if (inputRef.value) {
    inputRef.value.value = 'Vue 3 模板引用示例'
    getInputValue()
  }
}

// 2. 组件引用
const counterRef = ref(null)
const counterValue = ref(null)

const incrementCounter = () => {
  if (counterRef.value) {
    counterRef.value.increment()
  }
}

const getCounterValue = () => {
  if (counterRef.value) {
    counterValue.value = counterRef.value.count
  }
}

const resetCounter = () => {
  if (counterRef.value) {
    counterRef.value.reset()
    counterValue.value = 0
  }
}

// 计数器组件定义
const CounterComponent = {
  template: `
    <div class="counter">
      <div class="count">{{ count }}</div>
      <div class="buttons">
        <button @click="increment" class="btn btn-small">+</button>
        <button @click="decrement" class="btn btn-small">-</button>
      </div>
    </div>
  `,
  setup() {
    const count = ref(0)
    
    const increment = () => {
      count.value++
    }
    
    const decrement = () => {
      if (count.value > 0) {
        count.value--
      }
    }
    
    const reset = () => {
      count.value = 0
    }
    
    return {
      count,
      increment,
      decrement,
      reset
    }
  }
}

// 3. v-for 中的模板引用
const items = ref(['Vue 3', 'React', 'Angular', 'Svelte', 'Preact'])
const itemRefs = ref([])

const highlightRandomItem = async () => {
  // 确保所有引用都已更新
  await nextTick()
  
  // 重置所有高亮
  itemRefs.value.forEach(el => {
    if (el) {
      el.classList.remove('highlighted')
    }
  })
  
  // 高亮随机项目
  if (itemRefs.value.length > 0) {
    const randomIndex = Math.floor(Math.random() * itemRefs.value.length)
    const randomItem = itemRefs.value[randomIndex]
    if (randomItem) {
      randomItem.classList.add('highlighted')
      randomItem.scrollIntoView({ behavior: 'smooth', block: 'center' })
    }
  }
}

const resetHighlights = () => {
  itemRefs.value.forEach(el => {
    if (el) {
      el.classList.remove('highlighted')
    }
  })
}

// 4. 响应式引用和生命周期
const containerRef = ref(null)
const count = ref(3)
const containerDimensions = ref(null)

const increaseCount = () => {
  count.value++
}

const decreaseCount = () => {
  if (count.value > 1) {
    count.value--
  }
}

const measureContainer = async () => {
  await nextTick()
  if (containerRef.value) {
    const rect = containerRef.value.getBoundingClientRect()
    containerDimensions.value = {
      width: Math.round(rect.width),
      height: Math.round(rect.height)
    }
  }
}

// 监听count变化，自动测量容器尺寸
watch(count, async () => {
  await nextTick()
  measureContainer()
})

// 5. 组合式API高级用法
const weatherData = ref(null)
const loading = ref(false)
const error = ref('')

// 模拟天气API调用的组合式函数
const fetchWeather = async () => {
  loading.value = true
  error.value = ''
  
  try {
    // 模拟API延迟
    await new Promise(resolve => setTimeout(resolve, 1000))
    
    // 模拟数据
    const mockWeather = {
      temperature: Math.floor(Math.random() * 20) + 10, // 10-30°C
      condition: ['晴朗', '多云', '小雨', '阴天'][Math.floor(Math.random() * 4)],
      humidity: Math.floor(Math.random() * 40) + 40, // 40-80%
      windSpeed: Math.floor(Math.random() * 30) + 5, // 5-35 km/h
      pressure: Math.floor(Math.random() * 20) + 1000 // 1000-1020 hPa
    }
    
    weatherData.value = mockWeather
  } catch (err) {
    error.value = '获取天气数据失败'
  } finally {
    loading.value = false
  }
}

const refreshWeather = () => {
  fetchWeather()
}

// 组件挂载时获取天气数据
onMounted(() => {
  fetchWeather()
})

// 6. 自定义组合式函数
// 鼠标位置跟踪
const useMouseTracker = () => {
  const position = ref({ x: 0, y: 0 })
  
  const updatePosition = (e) => {
    position.value.x = e.clientX
    position.value.y = e.clientY
  }
  
  onMounted(() => {
    window.addEventListener('mousemove', updatePosition)
  })
  
  onUnmounted(() => {
    window.removeEventListener('mousemove', updatePosition)
  })
  
  return position
}

// 秒表功能
const useStopwatch = () => {
  const startTime = ref(0)
  const elapsed = ref(0)
  const isRunning = ref(false)
  const timer = ref(null)
  
  const start = () => {
    if (!isRunning.value) {
      startTime.value = Date.now() - elapsed.value
      isRunning.value = true
      timer.value = setInterval(() => {
        elapsed.value = Date.now() - startTime.value
      }, 10)
    }
  }
  
  const stop = () => {
    if (isRunning.value) {
      clearInterval(timer.value)
      isRunning.value = false
    }
  }
  
  const reset = () => {
    stop()
    elapsed.value = 0
  }
  
  const formatTime = () => {
    const ms = Math.floor(elapsed.value % 1000 / 10)
    const seconds = Math.floor(elapsed.value / 1000) % 60
    const minutes = Math.floor(elapsed.value / 60000)
    
    return `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}.${ms.toString().padStart(2, '0')}`
  }
  
  onUnmounted(() => {
    clearInterval(timer.value)
  })
  
  return {
    elapsed,
    isRunning,
    start,
    stop,
    reset,
    formatTime
  }
}

// 使用自定义组合式函数
const mousePosition = useMouseTracker()
const { elapsed: stopwatchElapsed, isRunning, start: startStopwatch, stop: stopStopwatch, reset, formatTime } = useStopwatch()

const startStop = () => {
  if (isRunning.value) {
    stopStopwatch()
  } else {
    startStopwatch()
  }
}

const formattedTime = ref('00:00.00')

// 格式化时间的计算属性
watch(stopwatchElapsed, () => {
  formattedTime.value = formatTime()
})
</script>

<style scoped>
.template-refs-demo {
  max-width: 1200px;
  margin: 0 auto;
  padding: 20px;
}

h2 {
  color: #333;
  margin-bottom: 30px;
  text-align: center;
}

.introduction {
  background-color: #f8f9fa;
  padding: 20px;
  border-radius: 8px;
  margin-bottom: 30px;
}

.demo-section {
  background-color: #fff;
  border-radius: 12px;
  padding: 24px;
  margin-bottom: 30px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

h3 {
  color: #42b983;
  margin-bottom: 20px;
  border-bottom: 2px solid #42b983;
  padding-bottom: 10px;
}

.demo-content {
  margin-bottom: 20px;
}

.controls {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  margin-top: 15px;
}

.btn {
  background-color: #42b983;
  color: white;
  border: none;
  padding: 8px 16px;
  border-radius: 6px;
  cursor: pointer;
  font-size: 14px;
  transition: background-color 0.3s;
}

.btn:hover {
  background-color: #3aa876;
}

.btn-small {
  padding: 4px 12px;
  font-size: 18px;
  line-height: 1;
  width: 36px;
  height: 36px;
}

.input {
  padding: 10px;
  border: 1px solid #ddd;
  border-radius: 6px;
  width: 300px;
  margin-right: 10px;
}

.result {
  margin-top: 15px;
  padding: 10px;
  background-color: #e3f2fd;
  border-radius: 6px;
  font-weight: bold;
}

/* 计数器组件样式 */
.counter {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 20px;
  background-color: #f8f9fa;
  border-radius: 8px;
}

.count {
  font-size: 48px;
  font-weight: bold;
  color: #42b983;
  margin-bottom: 15px;
}

.counter .buttons {
  display: flex;
  gap: 10px;
}

/* v-for 项目样式 */
.item {
  padding: 15px;
  margin-bottom: 10px;
  background-color: #f0f0f0;
  border-radius: 6px;
  transition: all 0.3s ease;
}

.item.highlighted {
  background-color: #ffeb3b;
  transform: scale(1.02);
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}

/* 容器尺寸测量样式 */
.container {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  padding: 20px;
  background-color: #f8f9fa;
  border-radius: 8px;
  min-height: 100px;
  margin-bottom: 15px;
}

.box {
  width: 50px;
  height: 50px;
  background-color: #2196f3;
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 6px;
  font-weight: bold;
}

/* 天气组件样式 */
.weather-widget {
  background-color: #e1f5fe;
  border-radius: 12px;
  padding: 20px;
  text-align: center;
}

.weather-widget h4 {
  color: #0288d1;
  margin-bottom: 15px;
}

.weather-main {
  margin-bottom: 20px;
}

.temperature {
  font-size: 48px;
  font-weight: bold;
  color: #0277bd;
  margin-bottom: 10px;
}

.condition {
  font-size: 20px;
  color: #01579b;
}

.weather-details {
  display: flex;
  justify-content: space-around;
  flex-wrap: wrap;
  gap: 15px;
  margin-bottom: 15px;
}

.detail {
  background-color: white;
  padding: 10px 15px;
  border-radius: 6px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.loading {
  padding: 20px;
  color: #666;
}

.error {
  padding: 20px;
  color: #d32f2f;
  background-color: #ffebee;
  border-radius: 6px;
}

/* 鼠标跟踪器样式 */
.mouse-tracker {
  position: relative;
  height: 200px;
  background-color: #f3e5f5;
  border-radius: 8px;
  margin-bottom: 20px;
  padding: 20px;
  overflow: hidden;
  cursor: crosshair;
}

.mouse-tracker h4 {
  color: #7b1fa2;
  margin-bottom: 10px;
}

.mouse-info {
  background-color: white;
  padding: 10px;
  border-radius: 6px;
  display: inline-block;
  margin-bottom: 20px;
}

.tracker-dot {
  position: absolute;
  width: 20px;
  height: 20px;
  background-color: #e91e63;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  pointer-events: none;
  transition: transform 0.1s ease;
}

/* 秒表样式 */
.stopwatch {
  background-color: #fff3e0;
  border-radius: 8px;
  padding: 20px;
  text-align: center;
}

.stopwatch h4 {
  color: #e65100;
  margin-bottom: 15px;
}

.time {
  font-size: 36px;
  font-weight: bold;
  color: #bf360c;
  font-family: monospace;
  margin-bottom: 20px;
  background-color: white;
  padding: 10px;
  border-radius: 6px;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .input {
    width: 100%;
    margin-bottom: 10px;
  }
  
  .controls {
    flex-direction: column;
  }
  
  .btn {
    width: 100%;
  }
  
  .weather-details {
    flex-direction: column;
    align-items: center;
  }
  
  .detail {
    width: 100%;
    max-width: 200px;
  }
  
  .temperature {
    font-size: 36px;
  }
  
  .time {
    font-size: 28px;
  }
}
</style>